/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.base.manager.impl;

import com.xy.biz.base.dao.BizCodeDao;
import com.xy.biz.base.dao.BizCodeIncrDao;
import com.xy.biz.base.domain.bo.BizCodeBO;
import com.xy.biz.base.domain.converter.BizCodeConverter;
import com.xy.biz.base.domain.po.BizCodeIncrPO;
import com.xy.biz.base.domain.po.BizCodePO;
import com.xy.biz.base.manager.BizCodeManager;
import com.xy.biz.base.support.bizcode.BizCodeGenerator;
import com.xy.lang.exception.ObjectNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.Map;

import static com.xy.biz.base.support.bizcode.BizCodeGenerator.ALGORITHM_SERVICE_PREFIX;

/**
 * 
 * 
 * @author zsp
 * @date 2020-8-25
 */
@Service
public class BizCodeManagerImpl implements BizCodeManager {

	@Autowired
	private BizCodeDao bizCodeDao;
	@Autowired
	private BizCodeIncrDao bizCodeIncrDao;
	@Autowired
	private Map<String, BizCodeGenerator> bizCodeGeneratorMap;

	@Override
	public BizCodeBO getBizCode(String code, Long tenantId) {
		BizCodePO bizCodePO = bizCodeDao.getBizCodeByCode(code, tenantId);
		BizCodeBO bizCodeBO = null;
		if(bizCodePO != null) {
			BizCodeGenerator bizCodeGenerator = bizCodeGeneratorMap.get(ALGORITHM_SERVICE_PREFIX + bizCodePO.getAlgorithm());
			if(null == bizCodeGenerator) {
				throw new ObjectNotFoundException("未定义的算法：" + bizCodePO.getAlgorithm());
			}
			bizCodeBO = BizCodeConverter.fromPO(bizCodePO);
			long timestamp = bizCodeGenerator.getTimestamp();
			bizCodeBO.setTimestamp(timestamp);
			Integer currentValue = bizCodeIncrDao.getBizCodeIncr(bizCodeBO.getBizCodeId(), timestamp);
			bizCodeBO.setCurrentValue(null == currentValue ? 0 : currentValue);
		}
		return bizCodeBO;
	}

	@Override
	public void getBizCodeCurrentValue(BizCodeBO bizCodeBO) {
		Integer currentValue = bizCodeIncrDao.getBizCodeIncr(bizCodeBO.getBizCodeId(), bizCodeBO.getTimestamp());
		bizCodeBO.setCurrentValue(null == currentValue ? 0 : currentValue);
	}

	@Override
	public int updateBizCodeIncr(BizCodeBO bizCodeBO, Integer nextValue) {
		int affectedRows = bizCodeIncrDao.updateBizCodeIncr(bizCodeBO.getBizCodeId(),
				bizCodeBO.getTimestamp(),
				nextValue,
				bizCodeBO.getCurrentValue());
		if(affectedRows == 0 && !bizCodeBO.isHasTryToSaved() ) {
			try {
				affectedRows = bizCodeIncrDao.saveBizCodeIncr(BizCodeIncrPO.builder()
						.bizCodeId(bizCodeBO.getBizCodeId())
						.timestamp(bizCodeBO.getTimestamp())
						.currentValue(nextValue)
						.build());
			} catch (DuplicateKeyException e) {
				affectedRows = 0;
				bizCodeBO.setHasTryToSaved(true);
			}
		}
		return affectedRows;
	}
	
}
